#include <iostream>
#include <unistd.h>
#include <pthread.h>
#include <queue>

using namespace std;
class Task//生产者派发给消费者的任务
{
  public:
      int _x;
      int _y;
  public:
      Task(int x,int y)
        :_x(x),_y(y)
      {}
      Task()
      {}
      int sum()
      {
        return _x+_y;

      }


};


class BlockQueue
{
  private://成员变量
    pthread_mutex_t lock;// 
    pthread_cond_t consumer_cond;//消费者的等待条件
    pthread_cond_t productor_cond;//生产者的等待条件
    queue<Task> q;//队列
    size_t _cpacity;//队列最大容量

  private://私有接口

    void QueueLock()//锁定
    {
      pthread_mutex_lock(&lock);

    }                              
    void QueueUnLock()//解锁
    {
      pthread_mutex_unlock(&lock);
                                            
    }
    bool IsFull()
    {
      return q.size()>=_cpacity;                                          
    }
    bool IsEmpty()
    {
      return q.empty();

    }
    void WakeUpConsumber()//唤醒消费者
    {
      cout<<"【唤醒消费者】"<<endl;
      pthread_cond_signal(&consumer_cond);                                                        
    }
    void WakeUpProductor()//唤醒生产者
    {
      cout<<"【唤醒生产者】"<<endl;
      
      pthread_cond_signal(&productor_cond);
    }
    
    void ConsumberWait()//消费者等待唤醒条件
    
    {
    
      cout<<"队列已经空了，消费者睡觉了"<<endl;
      
      pthread_cond_wait(&consumer_cond,&lock);
                                                                      
      
    }
    
    void ProductorWait()//生产者等待唤醒条件
    
    {
    
      cout<<"队列已经满了，生产者睡觉了"<<endl;
      
      pthread_cond_wait(&productor_cond,&lock);
                                                                          
      
    }
                                                            

  public://对外接口
    
    BlockQueue(int capacity)//构造函数
    
      :_cpacity(capacity)
      
      {
      
        pthread_mutex_init(&lock,nullptr);
        
        pthread_cond_init(&consumer_cond,nullptr);
        
        pthread_cond_init(&productor_cond,nullptr);
        

        
      }
      
    ~BlockQueue()//析构
    
    {
    
      pthread_mutex_destroy(&lock);
      
      pthread_cond_destroy(&consumer_cond);
      
      pthread_cond_destroy(&productor_cond);
                                                                            
      
    }
    

    
    size_t getcapacity()
    
    {
    
      return _cpacity-q.size();
      

      
    }
    
    void Push(Task t)//生产者放数据
    
    {
    
      QueueLock();//进入临界资源
      
      while(IsFull())//如果队已经满了,注意使用while防止挂起失败
      
      {
      
        sleep(1);
        
        WakeUpConsumber();//唤醒消费者
        
        ProductorWait();//生产者睡觉
                                                                                                  
        
      } 
      
      q.push(t);//没有满就push
      
      QueueUnLock();//走出临界资源·
    }
    
    void Get(Task& t)//消费者拿数据
    
    {
    
      QueueLock();
      
      while(IsEmpty())//如果队列空了,注意使用while防止挂起失败
      
      {
      
        sleep(2);
        
        WakeUpProductor();//唤醒生产者
        
        ConsumberWait();//消费者睡觉
        

        
      }
      
      t=q.front();
      
      q.pop();
      
      QueueUnLock();
      

      
    }




};


